const validator = require('validator')

class Rule {
    constructor(name, msg, ...params) {
        Object.assign(this, {
            name,
            msg,
            params
        })
    }

    validate(value) {
        if (this.name == 'isOptional')
            return new RuleResult(true)
        if (!validator[this.name](value + '', ...this.params)) {
            return new RuleResult(false, this.msg || this.message || '参数错误')
        }
        return new RuleResult(true, '')
    }
}

class RuleResult {
    constructor(result, msg = '') {
        Object.assign(this, {
            result,
            msg
        })
    }
}

class Validator{
    constructor() {
        this.data = {}
        this.errMsgs=[]
    }

    validate(ctx) {
        // 提取参数
        this.data = this._assembleAllParams(ctx)
        // 开始校验
        for (const key in this.rules) {
            this._check(key)
        }
        if (this.errMsgs.length > 0) {
            throw new global.errs.ParameterException(this.errMsgs)
        }
        return this
    }

    get(keys) {
        const [source, key] = keys.split('.')
        return !key ? this.data[source] : this.data[source][key]
    }
    _assembleAllParams(ctx) {
        return {
            body: ctx.request.body,
            query: ctx.request.query,
            path: ctx.params,
            header: ctx.request.header
        }
    }

    _getParamsValue(key) {
        let value 

        if (value = this.get('body.' + key)) {
            return value
        }
        if (value = this.get('query.' + key)) {
            return value
        }
        if (value = this.get('path.' + key)) {
            return value
        }
    }

    _check(key) {

        const value = this._getParamsValue(key)
        if (!value) {
            throw new global.errs.ParameterException()
        }
        this.rules[key].forEach(rule => {
            const ruleResult = rule.validate(value)
            if (!ruleResult.result) {
                this.errMsgs.push(ruleResult.msg)
            }
        })
    }
}

class TokenValidator extends Validator{
    constructor() {
        super()
        this.rules = {
            name: [
                new Rule('isLength', 'token长度不符合校验规则', {
                    max: 11,
                    min:5
                }),
                new Rule('isInt')
            ]
        }
    }
}

module.exports = {
    Rule,TokenValidator,Validator
}